package com.dq.controller.wx.pay;

import com.dq.domain.position.OrgPosition;
import com.dq.domain.subscribe.Subscribe;
import com.dq.domain.sys.user.Account;
import com.dq.exception.customException.AdminException;
import com.dq.repository.user.SubscribeRepository;
import com.dq.service.AllService;
import com.dq.utils.DateUtils;
import com.dq.vo.Vo;
import com.dq.wx.pay.WxPayUtils;
import com.dq.wx.pay.async.WxPayAsyncMethod;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxScanPayNotifyResult;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;

@RestController
@RequestMapping("/wx/pay/")
public class WxPayController extends AllService {
    private static final Logger log = LoggerFactory.getLogger(WxPayController.class);

    @Autowired
    private WxPayAsyncMethod wxPayAsyncMethod;

    @ApiOperation(value = "原生的统一下单接口 - NATIVE")
    @GetMapping("unifiedOrder2nativeTopUp/{id}")
    public Vo unifiedOrder2nativeTopUp(@PathVariable Long id) throws WxPayException {
        Account account = dao.get(Account.class, id);
        if(account == null) {
            throw new AdminException("记录不存在, id: " + id);
        }
        String outTradeNo = account.getOrderNo();
        BigDecimal price = account.getPrice();
        if(price == null) {
            throw new AdminException("支付金额为空");
        }
        // 支付金额, 单位分, 1
        Integer totalFee = price.multiply(new BigDecimal("100")).intValue();
        // 商品描述
//        String body = "商品描述";
        String body = outTradeNo;
        // 商品Id, trade_type=NATIVE，此参数必传。此id为二维码中包含的商品Id，商户自行定义, 类型：String(32);
        String productId = account.getUserCard().getId().toString();

        Long loginUserId = account.getUser().getId();

        // 获取 NATIVE 支付 需要的二维码url
        String ossQrUrl = WxPayUtils.unifiedOrder2native2qr(outTradeNo, body, totalFee, productId, loginUserId);
        return new Vo(ossQrUrl);
    }

    @ApiOperation(value = "原生的统一下单接口 - NATIVE")
    @GetMapping("unifiedOrder2native/{orderId}")
    public Vo publish(@PathVariable Long orderId) throws WxPayException {
        Subscribe subscribe = dao.get(Subscribe.class, orderId);
        if(subscribe == null) {
            throw new AdminException("订单不存在, orderId: " + orderId);
        }
        String outTradeNo = subscribe.getSubscribeNo();
        BigDecimal price = subscribe.getServiceProject().getProjectPrice();
        if(price == null) {
            throw new AdminException("订单支付金额为空");
        }
        // 支付金额, 单位分, 1
        Integer totalFee = price.multiply(new BigDecimal("100")).intValue();
        // 商品描述
//        String body = "商品描述";
        String body = outTradeNo;
        // 商品Id, trade_type=NATIVE，此参数必传。此id为二维码中包含的商品Id，商户自行定义, 类型：String(32);
        String productId = subscribe.getServiceProject().getId().toString();

        Long loginUserId = subscribe.getWxUser().getId();

        // 获取 NATIVE 支付 需要的二维码url
        String ossQrUrl = WxPayUtils.unifiedOrder2native2qr(outTradeNo, body, totalFee, productId, loginUserId);
        return new Vo(ossQrUrl);
    }

    /**
     * 回调接口 需要放行
     * 与扫码相比转化参数更多
     */
    @ApiOperation(value = "支付回调通知处理")
    @PostMapping("nologin/notify/order")
    public String parseOrderNotifyResult(@RequestBody String xmlData) {
        // 手动处理异常, 使中间逻辑是否成功, 都给微信返回成功, 避免微信一直回调, 在本地做记录
        try {
            log.info(">>>>  支付回调通知处理, 接收原始数据包: {}", xmlData);
            final WxPayOrderNotifyResult notifyResult = WxPayUtils.wxPayService.parseOrderNotifyResult(xmlData);
            log.info("<<<<  支付回调通知处理, 转换原始数据包: {}", notifyResult);
            // 交易类型, JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付
            String tradeType = notifyResult.getTradeType();
            System.out.println(">>>>  支付回调通知处理, 交易类型: "+ tradeType);

            // TODO 根据自己业务场景需要构造返回对象 -------------------- begin
            String outTradeNo = notifyResult.getOutTradeNo();
            String transactionId = notifyResult.getTransactionId();
            // 单位分
            Integer totalFee = notifyResult.getTotalFee();
            // 支付完成时间，格式为yyyyMMddHHmmss，如2009年12月25日9点10分10秒表示为20091225091010。其他详见时间规则
            String timeEnd = notifyResult.getTimeEnd();
            long payTime = DateUtils.dateTime("yyyyMMddHHmmss", timeEnd).getTime();
            String sign = notifyResult.getSign();
            System.out.println(">>>>  支付回调通知处理, sign: "+ sign);

            if(outTradeNo.contains("Ac_")) {
                wxPayAsyncMethod.parseOrderNotifyResultAsync02(outTradeNo, transactionId, totalFee, payTime, sign);
            }else {
                wxPayAsyncMethod.parseOrderNotifyResultAsync(outTradeNo, transactionId, totalFee, payTime, sign);
            }
            // TODO 根据自己业务场景需要构造返回对象 -------------------- end

        }catch (Exception e) {
            e.printStackTrace();
            log.error("微信 支付回调通知处理 [异常], 返回微信成功, 本地记录; msg: {}", e.getMessage());
        }

        return WxPayNotifyResponse.success("成功");
    }

    @ApiOperation(value = "查询订单")
    @GetMapping("/queryOrder/{outTradeNo}")
    public Vo queryOrder(@PathVariable String outTradeNo) throws WxPayException {
        WxPayOrderQueryResult result = WxPayUtils.queryOrder("", outTradeNo);
        return new Vo(result);
    }

    /**
     * 支付成功, 不能关单, 关闭后的订单号不能再次用来调用统一下单接口
     * @param outTradeNo 商户系统内部订单号
     */
    @ApiOperation(value = "关闭订单")
    @GetMapping("closeOrder/{outTradeNo}")
    public Vo closeOrder(@PathVariable String outTradeNo) throws WxPayException {
        return new Vo(WxPayUtils.closeOrder(outTradeNo));
    }

}
